package hc.trip.airticket.httpclient;

import hc.trip.airticket.bean.FlightInfo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;

public class HttpRequestProxy {
	// 超时间隔
	private static int connectTimeOut = 60000;
	// 让connectionmanager管理httpclientconnection时是否关闭连接
	private static boolean alwaysClose = false;
	// 返回数据编码格式
	private static String encoding = "UTF-8";

	private final HttpClient client = new HttpClient(
			new SimpleHttpConnectionManager(alwaysClose));

	public HttpClient getHttpClient() {
		return client;
	}

	/**
	 * 用法： HttpRequestProxy hrp = new HttpRequestProxy();
	 * hrp.doRequest("http://www.163.com",null,null,"gbk");
	 * 
	 * @param url
	 *            请求的资源ＵＲＬ
	 * @param postData
	 *            POST请求时form表单封装的数据 没有时传null
	 * @param header
	 *            request请求时附带的头信息(header) 没有时传null
	 * @param encoding
	 *            response返回的信息编码格式 没有时传null
	 * @return response返回的文本数据
	 * @throws Exception
	 */
	public String doRequest(String url, Map postData, Map header,
			String encoding) throws Exception {
		String responseString = null;
		// 头部请求信息
		Header[] headers = null;
		if (header != null) {
			Set entrySet = header.entrySet();
			int dataLength = entrySet.size();
			headers = new Header[dataLength];
			int i = 0;
			for (Iterator itor = entrySet.iterator(); itor.hasNext();) {
				Map.Entry entry = (Map.Entry) itor.next();
				headers[i++] = new Header(entry.getKey().toString(), entry
						.getValue().toString());
			}
		}
		// post方式
		if (postData != null) {
			PostMethod postRequest = new PostMethod(url.trim());
			if (headers != null) {
				for (int i = 0; i < headers.length; i++) {
					postRequest.setRequestHeader(headers[i]);
				}
			}
			Set entrySet = postData.entrySet();
			int dataLength = entrySet.size();
			NameValuePair[] params = new NameValuePair[dataLength];
			int i = 0;
			for (Iterator itor = entrySet.iterator(); itor.hasNext();) {
				Map.Entry entry = (Map.Entry) itor.next();
				params[i++] = new NameValuePair(entry.getKey().toString(),
						entry.getValue().toString());
			}
			postRequest.setRequestBody(params);
			try {
				responseString = this.executeMethod(postRequest, encoding);

			} catch (ConnectTimeoutException e) {
				// TODO: handle exception
				throw e;
			} catch (Exception e) {
				throw e;
			} finally {
				postRequest.releaseConnection();
			}
		}
		// get方式
		if (postData == null) {
			GetMethod getRequest = new GetMethod(url.trim());
			if (headers != null) {
				for (int i = 0; i < headers.length; i++) {
					getRequest.setRequestHeader(headers[i]);
				}
			}
			try {
				responseString = this.executeMethod(getRequest, encoding);
			} catch (Exception e) {
				e.printStackTrace();
				throw e;
			} finally {
				getRequest.releaseConnection();
			}
		}

		return responseString;
	}

	@SuppressWarnings("deprecation")
	private String executeMethod(HttpMethod request, String encoding)
			throws Exception {
		String responseContent = null;
		InputStream responseStream = null;
		BufferedReader rd = null;
		try {

			// 设置超时时间
			client.setConnectionTimeout(connectTimeOut);
			this.getHttpClient().executeMethod(request);
			// 设置cookie为httpclient自动管理
			client.getParams().setCookiePolicy(
					CookiePolicy.BROWSER_COMPATIBILITY);
			client.getParams().setParameter(
					"http.protocol.single-cookie-header", true);
			responseStream = request.getResponseBodyAsStream();
			// System.out.println(request.getResponseHeader("X-Requested-With"));
			if (encoding != null && encoding.length() > 0) {
				rd = new BufferedReader(new InputStreamReader(responseStream,
						encoding));
			} else {
				rd = new BufferedReader(new InputStreamReader(responseStream));
			}
			String tempLine = rd.readLine();
			StringBuffer tempStr = new StringBuffer();
			String crlf = System.getProperty("line.separator"); // 换行符
			while (tempLine != null) {
				tempStr.append(tempLine);
				 // tempStr.append(crlf);
				tempLine = rd.readLine();
			}

			responseContent = tempStr.toString();

			Header locationHeader = request.getResponseHeader("location");
			// 返回代码为302,301时，表示页面己经重定向，则重新请求location的url，这在
			// 一些登录授权取cookie时很重要
			if (locationHeader != null) {
				String redirectUrl = locationHeader.getValue();
				this.doRequest(redirectUrl, null, null, null);
			}
		} catch (ConnectTimeoutException e) { // 超时
			// TODO: handle exception
			e.printStackTrace();
			throw e;
		} catch (HttpException e) {
			e.printStackTrace();
			throw new Exception(e.getMessage());
		} catch (IOException e) {
			throw new Exception(e.getMessage());
		} finally {
			if (rd != null)
				try {
					rd.close();
				} catch (IOException e) {
					throw new Exception(e.getMessage());
				}
			if (responseStream != null)
				try {
					responseStream.close();
				} catch (IOException e) {
					throw new Exception(e.getMessage());

				}
		}
		return responseContent;
	}

	/**
	 * 从httpclient中组装cookie
	 * 
	 * @return String
	 */
	public String getCookieStr() {
		Cookie[] cookies = client.getState().getCookies();
		StringBuilder builder = new StringBuilder();
		int i = 0;
		for (Cookie cookie : cookies) {
			++i;
			builder.append(cookie.getName()).append("=").append(
					cookie.getValue());
			if (i < cookies.length) {
				builder.append(";");
			}
		}
		return builder.toString();
	}

}